package com.lanchetech.admin.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.lanchetech.admin.service.CategoryService;
import com.lanchetech.bean.request.CategoryReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.CategoryInfoResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.CategoryEditVO;
import com.lanchetech.bean.vo.ShopCategoryEditVO;
import com.lanchetech.common.enums.CategoryTypeEnum;
import com.lanchetech.common.enums.DeletedEnum;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    FrontBackCategoryMapper frontBackCategoryMapper;

    @Autowired
    CategoryBrandMapper categoryBrandMapper;

    @Autowired
    CategorySpecMapper categorySpecMapper;

    @Autowired
    AttributeMapper attributeMapper;

    @Autowired
    SpuAttributeMapper spuAttributeMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    ShopCategoryMapper shopCategoryMapper;

    @Override
    public ResultData<BasePageResp<Category>> getCategoryPage(CategoryReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Category> list = categoryMapper.findAllAdminPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<List<Category>> getTwoLevelCategoryList(Byte type) {
        ValueOperations<String, List<Category>> operations = redisTemplate.opsForValue();
        String key = "GetTwoLevelCategoryList:" + type.toString();
        List<Category> result = operations.get(key);
        if (result == null) {
            result = categoryMapper.getTwoLevelCategoryList(type);
            operations.set(key, result);
        }
        return new ResultData<>(result);
    }

    @Override
    public ResultData<List<Category>> getAllCategoryList(Byte type) {
        ValueOperations<String, List<Category>> operations = redisTemplate.opsForValue();
        String key = "GetAllCategoryList:" + type.toString();
        List<Category> result = operations.get(key);
        if (result == null) {
            result = categoryMapper.findAllByType(type);
            operations.set(key, result);
        }
        return new ResultData<>(result);
    }

    @Override
    public ResultData<List<Category>> getRootCategoryList(Byte type) {
        ValueOperations<String, List<Category>> operations = redisTemplate.opsForValue();
        String key = "GetRootCategoryList:" + type.toString();
        List<Category> result = operations.get(key);
        if (result == null) {
            result = categoryMapper.findAllRootByType(type);
            operations.set(key, result);
        }
        return new ResultData<>(result);
    }

    @Override
    public ResultData<List<Category>> getChildrenCategory(Long id) {
        return new ResultData<>(categoryMapper.findAllByPid(id));
    }

    /**
     * 模糊删除redis，支持通配符
     *
     * @param key
     */
    private void deleteRedisByKey(String key) {
        Set<String> keys = redisTemplate.keys(key);
        if (!CollectionUtils.isEmpty(keys)) {
            redisTemplate.delete(keys);
        }
    }

    @Override
    public BaseResp editCategory(CategoryEditVO categoryEditVO) {
        ValueOperations<String, Long> operations = redisTemplate.opsForValue();
        operations.set("CategoryModifyTime", new Date().getTime());


        Category category = new Category();
        BeanUtils.copyProperties(categoryEditVO, category);

        // 如果类目新增或修改，则清除所有缓存
        deleteRedisByKey("GetTwoLevelCategoryList*");
        deleteRedisByKey("GetAllCategoryList*");
        deleteRedisByKey("GetRootCategoryList*");

        if (CategoryTypeEnum.FRONT.getType().equals(category.getType())) {
            // 如果前台类目变更了，则删除所有前台类目缓存
            deleteRedisByKey("CategoryList*");
        }

        if (CategoryTypeEnum.BACK.getType().equals(category.getType())) {
            // 如果后台类目变更了，则删除首页类目缓存
            deleteRedisByKey("HomeInfoResp");
        }

        if (category.getId() == null) {
            category.setDeleted((byte) 0);
            category.setCreatedAt(new Date());
            category.setUpdatedAt(new Date());
            categoryMapper.insert(category);

            // 如果是前台类目，关联后台类目
            if (CategoryTypeEnum.FRONT.getType().equals(category.getType()) && !CollectionUtils.isEmpty(categoryEditVO.getRelateCategory())) {
                frontBackCategoryMapper.batchInsert(categoryEditVO.getRelateCategory(), category.getId());
            }

            // 如果是后台类目，则关联品牌、销售属性
            if (CategoryTypeEnum.BACK.getType().equals(category.getType())) {
                if (!CollectionUtils.isEmpty(categoryEditVO.getBrandIds())) {
                    categoryBrandMapper.batchInsert(categoryEditVO.getBrandIds(), category.getId());
                }
                if (!CollectionUtils.isEmpty(categoryEditVO.getSpecIds())) {
                    categorySpecMapper.batchInsert(categoryEditVO.getSpecIds(), category.getId());
                }
                for (Attribute attribute : categoryEditVO.getAttributeList()) {
                    attribute.setCategoryId(category.getId());
                    attribute.setCreatedAt(new Date());
                    attribute.setUpdatedAt(new Date());
                    attributeMapper.insert(attribute);
                }
            }
        } else {
            category.setUpdatedAt(new Date());
            categoryMapper.updateByPrimaryKeySelective(category);

            // 关联后台类目
            frontBackCategoryMapper.deleteByFrontId(category.getId());
            if (CategoryTypeEnum.FRONT.getType().equals(category.getType()) && !CollectionUtils.isEmpty(categoryEditVO.getRelateCategory())) {
                frontBackCategoryMapper.batchInsert(categoryEditVO.getRelateCategory(), category.getId());
            }

            // 如果是后台类目，则关联品牌、销售属性
            if (CategoryTypeEnum.BACK.getType().equals(category.getType())) {
                categoryBrandMapper.deleteByCategoryId(category.getId());
                if (!CollectionUtils.isEmpty(categoryEditVO.getBrandIds())) {
                    categoryBrandMapper.batchInsert(categoryEditVO.getBrandIds(), category.getId());
                }
                categorySpecMapper.deleteByCategoryId(category.getId());
                if (!CollectionUtils.isEmpty(categoryEditVO.getSpecIds())) {
                    categorySpecMapper.batchInsert(categoryEditVO.getSpecIds(), category.getId());
                }

                // 自然属性，新增、删除、编辑
                List<Attribute> attributes = attributeMapper.findAllByCategoryId(category.getId());
                Map<Long, Boolean> attributesMap = new HashMap<>();
                for (Attribute attribute : attributes) {
                    attributesMap.put(attribute.getId(), true);
                }
                for (Attribute attribute : categoryEditVO.getAttributeList()) {
                    if (attribute.getId() == null) {
                        // 新增
                        attribute.setCategoryId(category.getId());
                        attribute.setCreatedAt(new Date());
                        attribute.setUpdatedAt(new Date());
                        attributeMapper.insert(attribute);
                    } else {
                        if (attributesMap.containsKey(attribute.getId())) {
                            // 编辑
                            attribute.setUpdatedAt(new Date());
                            attributeMapper.updateByPrimaryKeySelective(attribute);
                            // 已编辑过的标识false，其他的要删除
                            attributesMap.put(attribute.getId(), false);
                        }
                    }
                }

                for (Map.Entry<Long, Boolean> entry : attributesMap.entrySet()) {
                    // 需要删除的属性
                    if (entry.getValue()) {
                        attributeMapper.deleteByPrimaryKey(entry.getKey());
                        spuAttributeMapper.deleteByAttributeId(entry.getKey());
                    }
                }

            }
        }
        return new BaseResp();
    }

    @Override
    public ResultData<CategoryEditVO> getCategoryDetail(Long id) {
        Category category = categoryMapper.selectByPrimaryKey(id);
        CategoryEditVO categoryEditVO = new CategoryEditVO();
        BeanUtils.copyProperties(category, categoryEditVO);
        if (CategoryTypeEnum.FRONT.getType().equals(category.getType())) {
            List<FrontBackCategory> list = frontBackCategoryMapper.findAllByFrontId(category.getId());
            List<Long> result = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                result.add(list.get(i).getBackId());
            }
            categoryEditVO.setRelateCategory(result);
        } else {
            // 品牌
            List<CategoryBrand> brandList = categoryBrandMapper.findAllByCategoryId(id);
            List<Long> brandIds = new ArrayList<>();
            for (int i = 0; i < brandList.size(); i++) {
                brandIds.add(brandList.get(i).getBrandId());
            }

            // 销售属性
            List<CategorySpec> specList = categorySpecMapper.findAllByCategoryId(id);
            List<Long> specIds = new ArrayList<>();
            for (int i = 0; i < specList.size(); i++) {
                specIds.add(specList.get(i).getSpecId());
            }

            // 自然属性
            List<Attribute> attributes = attributeMapper.findAllByCategoryId(id);
            categoryEditVO.setBrandIds(brandIds);
            categoryEditVO.setSpecIds(specIds);
            categoryEditVO.setAttributeList(attributes);
        }

        return new ResultData<>(categoryEditVO);
    }

    @Override
    public BaseResp deleteCategory(Long id) {
        ValueOperations<String, Long> operations = redisTemplate.opsForValue();
        operations.set("CategoryModifyTime", new Date().getTime());

        categoryMapper.updateDeletedById((byte) 1, id);

        // 如果类目新增或修改，则清除所有缓存
        deleteRedisByKey("GetTwoLevelCategoryList*");
        deleteRedisByKey("GetAllCategoryList*");
        deleteRedisByKey("GetRootCategoryList*");
        deleteRedisByKey("CategoryList*");

        return new BaseResp();
    }

    @Override
    public ResultData<CategoryInfoResp> getCategoryInfo(Long id) {
        CategoryInfoResp resp = new CategoryInfoResp();
        resp.setAttributeList(attributeMapper.findAllByCategoryId(id));
        resp.setSpecList(categorySpecMapper.findAllSpecByCategoryId(id));
        resp.setBrandList(categoryBrandMapper.findAllBrandByCategoryId(id));
        return new ResultData<>(resp);
    }

    @Override
    public ResultData<Long> getCategoryModifyTime() {
        ValueOperations<String, Long> operations = redisTemplate.opsForValue();

        Long time = operations.get("CategoryModifyTime");
        if (time == null) {
            time = new Date().getTime();
            operations.set("CategoryModifyTime", time);
        }


        return new ResultData<>(time);
    }

}